package org.fly.service.impl;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import org.codehaus.jackson.type.TypeReference;
import org.fly.bean.*;
import org.fly.bean.query.*;
import org.fly.bean.warpper.BaseStatistics;
import org.fly.bean.warpper.ProductPriceWarpper;
import org.fly.bean.warpper.ProductWarpper;
import org.fly.dao.*;
import org.fly.enums.PriceType;
import org.fly.enums.TimeUnit;
import org.fly.service.ProductService;
import org.fly.utils.*;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.fly.bean.common.BusinessException;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
* Created by autoCode on 2018-01-29 16:38:01.
*/
@Service
public class ProductServiceImpl implements ProductService {

    @Autowired
    ProductDao productDao;
    @Autowired
    ProductNormDao productNormDao;
    @Autowired
    SupplierProductDao supplierProductDao;
    @Autowired
    CustomerLevelDao customerLevelDao;
    @Autowired
    SCLRDao sclrDao;
    @Autowired
    SupplierDao supplierDao;
    @Autowired
    BrandDao brandDao;


    @Override
    public List<Product> list(ProductQuery query) {
        queryPreHandle(query);
        List<Product> productList = productDao.list(query);
        List<String> productIdList =  productList.stream().map(p->p.getId()).collect(Collectors.toList());
        if(!productIdList.isEmpty()){
            List<ProductNorm>  productNorms= productNormDao.listByProductIds(productIdList);
            Map<String,ProductNorm> pnMap = productNorms.stream().
                    collect(Collectors.toMap(pn->pn.getProductId(), pn->pn));
            //现在一个商品只允许有一类规格
            productList.forEach(p->{
                ProductNorm productNorm =  pnMap.get(p.getId());
                p.setProductNorm(productNorm);
            });

        }
        return productList;
    }

    @Override
    public List<ProductWarpper> listWarpper(ProductQuery query) {
        List<ProductWarpper> warppers = null;
        List<Product> products = list(query);
        if(!products.isEmpty()){
            List<String> brandIdList = new ArrayList<>();
            products.forEach(p->{
                if(StringUtils.isNotBlank(p.getBrandId()) &&
                        !brandIdList.contains(p.getBrandId())){
                    brandIdList.add(p.getBrandId());
                }
            });
            if(!brandIdList.isEmpty()){
                List<Brand> brands = brandDao.listByIds(brandIdList);
                Map <String,Brand> brandMap=  brands.stream().collect(Collectors.toMap(e->e.getId(),e->e));
                warppers =  products.stream().map(e->{
                    ProductWarpper warpper = new ProductWarpper();
                    BeanUtils.copyProperties(e,warpper);
                    if(StringUtils.isNotBlank(e.getBrandId())){
                        warpper.setBrand(brandMap.get(e.getBrandId()));
                    }

                    return warpper;
                }).collect(Collectors.toList());
            }

        }
        return warppers;
    }

    @Override
    public long count(ProductQuery query) {
        queryPreHandle(query);
        return productDao.count(query);
    }

    @Override
    public Product findById(String id) {
        List ProductIdList  = new ArrayList();
        Product product = productDao.findById(id);
        if(product != null ){
            ProductIdList.add(id);
            List<ProductNorm>  productNorms= productNormDao.listByProductIds(ProductIdList);
            //现在一个商品只允许有一类规格
            if(productNorms != null && productNorms.size() ==1){
                product.setProductNorm(productNorms.get(0));

            }
        }

        return product;
    }

    @Transactional
    @Override
    //todo 需要维护供货商的规格信息表
    public void save(Product bean)  throws BusinessException {
        boolean needDelete = false;
        long now = System.currentTimeMillis();
        if(StringUtils.isNotBlank(bean.getId())){
            needDelete = true;
             productDao.update(bean);
        }else {
            bean.setId(UUIDFactory.random());
            bean.setCreateTime(now);
            productDao.insert(bean);
        }
        ProductNorm productNorm = bean.getProductNorm();
        if(needDelete){
            productNormDao.deleteByProductId(bean.getId());
        }
        if(productNorm != null ){
            productNorm.setProductId(bean.getId());
            if(StringUtils.isBlank(productNorm.getId())){
                productNorm.setId(UUIDFactory.random());
            }
            productNorm.setCreateTime(now);
            productNormDao.insert(bean.getProductNorm());
        }
    }

    @Override
    public void delete(String id) {
        productDao.delete(id);
    }

    @Override
    public List<BaseStatistics> statistics(ProductStatisticsQuery query) {
        ProductQuery productQuery = new ProductQuery();
        productQuery.setTimeBegin(query.getTimeBegin());
        productQuery.setTimeEnd(query.getTimeEnd());
        productQuery.setClazzId(query.getClazzId());
        productQuery.setRootClazzId(query.getRootClazzId());
        List<Product> productList = productDao.list(productQuery);
        if(productList.isEmpty()){
            return null;
        }
        Multimap<String,String> multimap = ArrayListMultimap.create();
        //获取数据中开始时间
        long realStartDay = productList.stream().
                mapToLong(Product::getCreateTime).reduce(Long.MAX_VALUE,(a,b)->a>b?b:a);
        //获取数据中的结束时间
        long realEndDAY =  productList.stream().mapToLong(Product::getCreateTime).reduce(0L,(a,b)->a<b?b:a);
        //构建对应时间间隔列表
        List<String> timeList = TimeUtil.buildFullList(realStartDay,realEndDAY, TimeUnit.valueOf(query.getGroupBy()));
        timeList.forEach(e->multimap.put(e,"0"));
        productList.forEach(e->multimap.put(TimeUtil.convert(e.getCreateTime(), TimeUnit.valueOf(query.getGroupBy())),"1"));
        List<BaseStatistics> list = timeList.stream().map(e->{
            BaseStatistics vo = new BaseStatistics();
            vo.setGroupBy(e);
            vo.setValue(  multimap.get(e).stream().reduce("0",(a,b)-> StringNumber.add(a,b)));
            return vo;
        }).collect(Collectors.toList());
        return list;
    }

    @Override
    public ProductPriceWarpper find(String productId, String customerId) {

        Product product = productDao.findById(productId);
        SupplierProductQuery supplierProductQuery = new SupplierProductQuery();
        supplierProductQuery.setProductId(productId);
        List<SupplierProduct>  supplierProductList = supplierProductDao.list(supplierProductQuery);
        List<SupplierProduct> top5 = top5(supplierProductList);
        List<String> top5SupplierIdList = top5.stream().map(sp->sp.getSupplierId()).collect(Collectors.toList());
        SCLRQuery sclrQuery = new SCLRQuery();
        sclrQuery.setSupplierIdList(top5SupplierIdList);
        sclrQuery.setCustomerId(customerId);
        List<SCLR>  sclrs  = sclrDao.list(sclrQuery);
        //供货商对于该客户的级别设置
        Map<String,SCLR> sclrMap = sclrs.stream().collect(Collectors.toMap(e->e.getSupplierId(),e->e));
        CustomerLevelQuery customerLevelQuery = new CustomerLevelQuery();
        customerLevelQuery.setSupplierIdList(top5SupplierIdList);
        List<CustomerLevel> customerLevels = customerLevelDao.list(customerLevelQuery);
        //供货商默认的级别map
        Map<String,CustomerLevel> customerLevelMap = customerLevels.stream().filter(e->e.getDefaultSet()  ==1 ).
                collect(Collectors.toMap(e->e.getSupplierId(),e->e));


        ProductNormQuery productNormQuery = new ProductNormQuery();
        productNormQuery.setProductId(productId);
        List<ProductNorm> normList = productNormDao.list(productNormQuery);
        ProductNorm productNorm = null;
        if(!normList.isEmpty()){
            productNorm = normList.get(0);
        }

        ProductPriceWarpper productPriceWarpper = new ProductPriceWarpper();
        productPriceWarpper.setProduct(product);
        productPriceWarpper.setProductNorm(productNorm);
        List<Supplier> suppliers = supplierDao.listByIds(top5SupplierIdList);
        productPriceWarpper.setSuppliers(suppliers);
        String customerLevel = "";
        Map<String,String> priceMap = new HashMap<>();
        productPriceWarpper.setPriceMap(priceMap);
        for(int i=0;i<top5.size();i++){

            SupplierProduct supplierProduct = top5.get(i);
            customerLevel = CustomerLevelUtils.getCustomerLevel(customerId,
                    supplierProduct.getSupplierId(),customerLevelMap,sclrMap);
            PriceUtils.mapPrice(priceMap,supplierProduct,customerLevel,productNorm);
        }
        return productPriceWarpper;
    }

    /**
     * 防止供货商过多，只取5条，
     * todo 暂时取前5条 后续增加算法
     * @return
     */
    private  List<SupplierProduct> top5(List<SupplierProduct>  supplierProductList){
        if(supplierProductList.size()>5){
            return supplierProductList.subList(0,5);
        }else {
            return supplierProductList;
        }
    }



    private Map<String,String> mapPrice( Product product,ProductNorm productNorm,SupplierProduct supplierProduct,
                                        Map<String,SCLR> sclrMap,
                                        Map<String,CustomerLevel> customerLevelMap){
        Map<String,String> mapPrice = new HashMap<>();
       String supplierId =  supplierProduct.getSupplierId();

        String configJson = supplierProduct.getConfigJson();
        if(PriceType.same.name().equals(supplierProduct.getPriceType())){
             Map <String,String> map= JsonUtils.decode(configJson, new TypeReference<Map<String, String>>(){});
             
        }
        return null;
    }

    private void queryPreHandle(ProductQuery query){
        if(StringUtils.isNotBlank(query.getQueryStr())){
            BrandQuery brandQuery = new BrandQuery();
            brandQuery.setName(query.getQueryStr());
            List<Brand> brands = brandDao.list(brandQuery);
            List<String> brandIdListForQueryStr =  brands.stream().map(e->e.getId()).collect(Collectors.toList());
            if(!brandIdListForQueryStr.isEmpty()){
                query.setBrandIdListForQueryStr(brandIdListForQueryStr);
            }

        }
    }


}
